//package com.dyz.wsw.config.security;
//
//import com.dyz.wsw.config.WswProperties;
//import com.dyz.wsw.utils.IPUtils;
//import com.dyz.wsw.common.consts.data.AccountConsts;
//import com.dyz.wsw.common.consts.web.HttpConst;
//import com.dyz.wsw.common.consts.web.JwtConst;
//import com.dyz.wsw.common.pojo.auth.Principal;
//import com.dyz.wsw.common.utils.security.JWTs;
//import com.dyz.wsw.common.utils.security.MD5;
//import com.dyz.wsw.domain.admin.repository.cache.IUserCacheRepository;
//import com.google.gson.Gson;
//import io.jsonwebtoken.Claims;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.http.HttpHeaders;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.GrantedAuthority;
//import org.springframework.security.core.authority.SimpleGrantedAuthority;
//import org.springframework.security.core.context.SecurityContext;
//import org.springframework.security.core.context.SecurityContextImpl;
//import org.springframework.security.web.server.context.ServerSecurityContextRepository;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Mono;
//
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * SpringSecurity暂时没有为webflux提供无状态的SpringSecurity上下文存取策略
// * 因为想要实现无状态的上下文存取，需要自己实现
// * 当前jwt的处理不通过，只是没有授权的相关信息，也就是即使你没有登录也能访问那些不需要授权的请求
// * @author dyz
// * Time 2024/7/9 21:59
// */
////@Component
//@Slf4j
//public class AuthorizationContextRepository implements ServerSecurityContextRepository, HttpConst, JwtConst, AccountConsts {
//
//    private final WswProperties wswProperties;
//
//    private final IUserCacheRepository iUserCacheRepository;
//
//
//    public AuthorizationContextRepository(IUserCacheRepository iUserCacheRepository,WswProperties wswProperties){
//        log.debug("创建授权类对象：AuthorizationContextRepository");
//        this.iUserCacheRepository = iUserCacheRepository;
//        this.wswProperties = wswProperties;
//    }
//
//    @Override
//    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
//        // 通常不需要在这里做太多事情，因为Spring Security会自动处理保存逻辑
//        // 但你可以在这里添加一些自定义的逻辑，比如日志记录等
//        return Mono.empty();
//    }
//
//    @Override
//    public Mono<SecurityContext> load(ServerWebExchange exchange) {
//        String requestPath = exchange.getRequest().getURI().getPath();
//        log.debug("请求URL：{}",requestPath);
//        //对于某些请求，不需要jwt校验直接返回empty即可
//        for (String uri : wswProperties.getPermitUri()) {
//            if (requestPath.startsWith(uri)) {
//                return Mono.empty();
//            }
//        }
//
//        HttpHeaders headers = exchange.getRequest().getHeaders();
//        log.debug("正在尝试检查本次请求头token信息，请求头：{}",headers);
//
//        //1.获取token
//        String token = getToken(headers);
//        //2.校验token
//        if(!isLegal(token)){
//            return Mono.empty();
//        }
//        //3.解析token
//        Claims claims = parseToken(token);
//        if(claims == null) return Mono.empty();
//
//        //4.检查token是否存在盗用
//        if(!checkSteal(exchange,claims)) return Mono.empty();
//
//        return getAuthentication(claims)
//                .flatMap(authentication -> {
//                    SecurityContextImpl context = new SecurityContextImpl();
//                    context.setAuthentication(authentication);
//                    log.debug("权限处理完成，现在可以根据已有权限来访问受保护资源了！");
//                    return Mono.just(context);
//                });
//    }
//
//    /**
//     * 从缓存中获取权限，并封装成authentication
//     * @param claims payload
//     * @return Mono<Authentication>
//     */
//    private Mono<Authentication> getAuthentication(Claims claims) {
//        long userId = Long.parseLong(claims.get(CLAIM_USER_ID).toString());
//        String username = claims.get(CLAIM_USER_NAME).toString();
//        return iUserCacheRepository.getUserState(userId)
//                .flatMap(userCachePO->{
//                    //如果为false，删除缓存中存在的用户
//                    if(userCachePO.getEnable()!=ENABLE_STATE_ON){
//                        String message = "您的账号【" + username + "】已经被禁用，将强制下线！";
//                        log.warn(message);
//                        return iUserCacheRepository.deleteUserInfo(userId).then(Mono.empty());
//                    }
//                    return Mono.just(userCachePO);
//                })
//                .flatMap(userCachePO->{
//                    // 否则续期缓存中的登录信息，并从缓存中获取用户的权限信息
//                    String authoritiesJsonString = userCachePO.getAuthoritiesJsonString();
//                    log.debug("当前用户的权限列表 = {}",authoritiesJsonString);
//                    // 将解析得到的用户数据创建为Authentication对象
//                    Principal principal = new Principal(); // 当事人
//                    principal.setId(userId);
//                    principal.setUsername(username);
//                    List<GrantedAuthority> authorities = parseRolesFromJson(authoritiesJsonString);
//                    log.debug("看看权限长啥样：{}",authorities);
//                    Authentication authentication = new UsernamePasswordAuthenticationToken(principal, null, authorities);
//                    return iUserCacheRepository.renewal(userId).then(Mono.just(authentication));
//                });
//    }
//
//    /**
//     * 检测token是否存在盗用
//     * @param claims payload
//     * @param exchange 本次请求
//     * @return 盗用结果 false-盗用 true-正常
//     */
//    private boolean checkSteal(ServerWebExchange exchange,Claims claims){
//        log.debug("开始检查JWT是否存在盗用的问题");
//        String jti = claims.get(CLAIM_JWT_JWI).toString();
//        log.debug("JWT中的特征码 = {}",jti);
//        String thisRequestAgent = exchange.getRequest().getHeaders().getFirst(HEADER_USER_AGENT);
//        String thisRequestIp = IPUtils.getIp(exchange);
//        log.debug("本次请求的客户端信息：{}",thisRequestAgent);
//        log.debug("本次请求的IP信息：{}",thisRequestIp);
//        String md5Jti = MD5.encrypt(thisRequestIp);
//        log.debug("本次请求计算得出的特征码：{}",md5Jti);
//        if(!jti.equals(md5Jti)){
//            log.warn("本次请求的信息与当初登录时完全不同，存在盗用风险！");
//            return false;
//        }
//        return true;
//    }
//
//    /**
//     * 获取token
//     * @param headers 本次请求头
//     * @return token
//     */
//    private String getToken(HttpHeaders headers){
//        String jwt = headers.getFirst(HEADER_AUTHORIZATION);
//        log.debug("客户端携带的JWT：{}", jwt);
//        return jwt;
//    }
//
//    /**
//     * 检测token是否合法
//     * @param token token
//     * @return 检测结果
//     */
//    private boolean isLegal(String token){
//        //判断JWT的基本有效性(没有必要尝试解析格式明显错误的JWT数据)
//        if(!StringUtils.hasText(token)||token.length()<JWT_MIN_LENGTH){
//            log.warn("当前请求中,客户端没有携带有效的JWT");
//            return false;
//        }
//        return true;
//    }
//
//    /**
//     * 解析token，获取token中数据
//     * @param token 被解析的token
//     * @return token payload数据
//     */
//    private Claims parseToken(String token) {
//        log.debug("尝试解析JWT数据...");
//        token = token.substring(wswProperties.getJwtPrefix().length()).trim();//去除前缀与首尾空白
//        log.debug("jwt:{}",token);
//        Claims claims;
//        try {
//            claims = JWTs.parse(token,wswProperties.getPrivateKey());
//        }catch (Exception e){
//            log.warn("token解析异常，异常信息：{}",e.getMessage());
//            return null;
//        }
//        log.debug("JWT包含的信息：{}",claims);
//        return claims;
//    }
//
//    private List<GrantedAuthority> parseRolesFromJson(String json) {
//        Gson gson = new Gson();
//        List list = gson.fromJson(json, List.class);
//        List<GrantedAuthority> authorities = new ArrayList<>();
//        for (Object o : list) {
//            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(o.toString());
//            authorities.add(authority);
//        }
//        return authorities;
//    }
//
//
//}
